home *** CD-ROM | disk | FTP | other *** search
/ MacGames Sampler / PHT MacGames Bundle.iso / MacSource Folder / Samples from the CD / C and C++ / sesame C ƒ / asample.c < prev    next >
C/C++ Source or Header  |  1986-10-06  |  19KB  |  653 lines

  1.  /*   SAMPLE C PROGRAM  */
  2.  
  3. /* This is just to show you how to get a Macintosh application */
  4. /* using this compiler.  Its style may not be the best, */
  5. /* but it does show you how.  For one thing, the whole thing */
  6. /* should be broken into separate files and compiled separatly */
  7. /* Separate compilation is just one of the neat things this  */
  8. /* compiler does. For more sample programs and documentation  */
  9. /* become a registered owner by paying for Sesame C. */
  10.  
  11. /* READ THE include file ~asample.inc for some general technical */
  12. /* information on using this compiler */
  13.  
  14. /* ASAMPLE.C is a simple editor.  It shows how to use almost every basic */
  15. /* thing you can do with Sesame C and the Macintosh environment. */
  16. /* It is simple and yet shows how you can get quite a lot from */
  17. /* the Macintosh routines, such as menus, windows, scrollbars, */
  18. /* and cut and paste textediting */
  19.  
  20. /* By the way, this takes quite a while to compile, mainly */
  21. /* because it is fair sized and filled with comments. */
  22. /* Separate compilation is really the way to go. */
  23.  
  24. #include ~asample.inc
  25.  
  26. /* Here are the program globals.  In other files (if there were any), */
  27. /* they would be declared extern (possibly in an include file) */
  28.  
  29.  char  seventrec[16],viewrect[8],pblock[100];
  30.  int   windptr,tehnd,scrollhnd; 
  31.  int   applemenu, filemenu, editmenu,curtop; 
  32.  
  33. start()   /* Must start with start  */
  34.           /* Used to initialize the Macintosh environment */
  35.  
  36. {
  37.     char  qdglob[206];
  38.   
  39.     TRAP(INITGRAF,&qdglob[202]:L);  /* screwy address, but correct */
  40.     TRAP(INITFONTS);
  41.     flushevents(-1);   /* flushevents is a registered routine, so we */
  42.                        /* can't use the TRAP directive */
  43.     TRAP(INITWINDOWS);
  44.     TRAP(INITMENUS);
  45.     TRAP(INITDIALOG,0:L);
  46.     TRAP(TEINIT);
  47.     TRAP(INITCURSOR);
  48.     main();
  49.  
  50. }
  51.  
  52. /* This is a normal structure for a Macintosh program. */
  53. /* First you do some setup stuff, then you loop though */
  54. /* an event loop forever until you quite.  You then */
  55. /* should unsetup yourself if necessary.  This program */
  56. /* takes the lazy way out and just ends, letting the Macintosh */
  57. /* finish up the cleanup */
  58.  
  59. main()
  60.  
  61. makemenu();
  62. openwindow("untitled");  /* start off with an open window */  
  63. while(events()==0);
  64. }
  65.  
  66. /* We just make a menu and keep it around.  Good style includes */
  67. /* enabling and disabling menu items depending on whether */
  68. /* they can be used.  */
  69.  
  70. makemenu()
  71.  
  72. {   char    pascalstr[256];
  73.  
  74.     ctopstr("*",pascalstr);
  75.     pascalstr[1]=20; /* set to apple icon */
  76.     applemenu=TRAP:L(NEWMENU,appleid:W,pascalstr);
  77.     ctopstr("Sample Sesame C Program;-;Modify at will",pascalstr);
  78.     TRAP(APPENDMENU,applemenu:L,pascalstr);
  79.     TRAP(INSERTMENU,applemenu:L,0:W);   /* insert in front */
  80.     
  81.     ctopstr("File",pascalstr);
  82.     filemenu=TRAP:L(NEWMENU,fileid:W,pascalstr);
  83.     ctopstr("New;Open;Close;Save;Save as...;Print;-;Quit/Q",pascalstr);
  84.     TRAP(APPENDMENU,filemenu:L,pascalstr);
  85.     TRAP(INSERTMENU,filemenu:L,0:W);   /* insert in front */
  86.  
  87.     ctopstr("Edit",pascalstr);
  88.     editmenu=TRAP:L(NEWMENU,editid:W,pascalstr);
  89.     ctopstr("Undo/Z;-;Cut/X;Copy/C;Paste/V;Clear;Select All/S",pascalstr);
  90.     TRAP(APPENDMENU,editmenu:L,pascalstr);
  91.     TRAP(INSERTMENU,editmenu:L,0:W);   /* insert in front */
  92.  
  93.     TRAP(DRAWMENUBAR);
  94.  
  95. }
  96.  
  97. openwindow(title)   /* Opens a window with the specified title */
  98.                     /* Note it does not open a file, just sets up the window */
  99.                     /* Also note, that for simplicity this application only */
  100.                     /* allows one window to be opened */
  101.    char    title[];
  102.    char    ptitle[64],boundrect[8],fontinfo[8];
  103.  
  104. /* The easiest way to define a window is with a resource.  This */
  105. /* is how you do it the old fashioned way  */
  106.  
  107. /* C and Pascal strings are completely different. */
  108. /* The Macintosh Toolbox understands only Pascal strings */
  109. /* Everytime you use a TRAP that expects a string or returns */
  110. /* a string you have to use these conversion functions.  They are */
  111. /* writen in assembler for speed's sake.  They expect two addreses, */
  112. /* one the address of the source string and the other the address of */
  113. /* of the result string.  Be careful!  They do not check for any */
  114. /* limits to the string sizes.  P.S. the other routine is called ptocstr */
  115.  
  116.    ctopstr(title,ptitle);
  117.    TRAP(SETRECT,&boundrect,5:W,45:W,507:W,337:W);
  118.    windptr=TRAP:L(NEWWINDOW,0,&boundrect,ptitle,1:B,4:W,-1,0:B,0);   
  119.    TRAP(SETPORT,windptr);
  120.    TRAP(TEXTFONT,4:W);
  121.    TRAP(TEXTSIZE,9:W);
  122.    TRAP(SETRECT,&viewrect,4:W,5:W,482:W,290:W);
  123.    tehnd=TRAP:L(TENEW,&viewrect,&viewrect);
  124.    
  125.    curtop=0;
  126.    TRAP(SETRECT,&boundrect,488:W,0:W,504:W,292:W);
  127.    scrollhnd=TRAP:L(NEWCONTROL,windptr:L,&boundrect,"",1:B,0:W,0:W,0:W,
  128.       16:W,0:L);
  129.    
  130. }
  131.  
  132. closewindow()  /* Close the window opened by openwindow */
  133.  
  134. {
  135.     TRAP(TEDISPOSE,tehnd:L);
  136.     TRAP(DISPOSEWINDOW,windptr);  /* simple */
  137.     windptr=0;
  138.     tehnd=0;
  139.     scrollhnd=0;
  140. }
  141.  
  142. update()
  143.  
  144. {
  145.     TRAP(SETPORT,windptr);
  146.     TRAP(BEGINUPDATE,windptr);
  147.     TRAP(TEUPDATE,&viewrect,tehnd:L);
  148.     TRAP(DRAWCONTROLS,windptr:L);
  149.     TRAP(ENDUPDATE,windptr);
  150. }
  151. putachar(c)
  152.     char   c;
  153. {
  154.     int    charpos;
  155.  
  156.     TRAP(TEKEY,c:W,tehnd:L);
  157.     setscrollmax();
  158.  
  159. }
  160.  
  161. events()
  162.  
  163. {
  164.    int    event;
  165.    
  166.    if(tehnd)TRAP(TEIDLE,tehnd:L);
  167.    if(TRAP:B(GETNEXTEVENT,0xffff:W,&seventrec))  /* trap any event */
  168.      {
  169.  
  170. /* getword is a special function writen in assembler to get a */
  171. /* two byte word from the specified address.  It is a quick and */
  172. /* useful way to get at some of the Macintosh data structures */
  173. /* Going the other way, we have a routine call putword(address,value) */
  174. /* that puts a word anywhere you want.  It would be nice to */
  175. /* have these for long words as well, though there is a way using */
  176. /* C that we show you later. */
  177.  
  178.       event=getword(&seventrec);  /* get the event */
  179.       if(event==1)return domouse();
  180.       else if(event==3)return keydown();
  181.       else if(event==5)return keydown();
  182.       else if(event==6)update();
  183.       else if(event==8)activate();
  184.      }
  185.    return 0;
  186. }
  187.  
  188. activate()
  189.  
  190. {
  191.    if(getword(&seventrec[14])&1)
  192.      {  /* activate */
  193.      TRAP(TEACTIVATE,tehnd);
  194.      }
  195.    else
  196.      {  /* deactivate */
  197.      TRAP(TEDEACTIVATE,tehnd);
  198.      }
  199. }
  200.  
  201. keydown()
  202. {
  203.    int   modifiers;
  204.    char  thekey;
  205.  
  206.    modifiers=getword(&seventrec[14]);
  207.    thekey=seventrec[5];
  208.    if(modifiers&256)
  209.      {
  210.      return domenu(TRAP:L(MENUKEY,thekey:W));
  211.      } 
  212.    else /* it a character so print it */
  213.      {
  214.      putachar(thekey);  /* a return key */
  215.      }
  216.    return 0;
  217. }
  218.  
  219.  
  220. domouse()
  221. {
  222.    int    *evwhere,windowloc,wwindptr,mselected,where,whichpart,wcntlhnd;
  223.    
  224.    evwhere=&seventrec[10];
  225.    where=*evwhere;
  226.    windowloc=TRAP:W(FINDWINDOW,where:L,&wwindptr:L);
  227.    if(windowloc==1)    /* in menubar */
  228.       { 
  229.       mselected=TRAP:L(MENUSELECT,where:L);
  230.       return domenu(mselected);
  231.       }
  232.    else if(windowloc==3)  /* in content of window.  This can be */
  233.                           /* the text part or the scrollbar */
  234.       {
  235.       TRAP(GLOBALTOLOCAL,&where);
  236.       whichpart=TRAP:W(FINDCONTROL,where:L,windptr:L,&wcntlhnd:L);
  237.  
  238.       if(whichpart==0)selecttext(where);  /* in the text part */
  239.  
  240.                /* now check if in the scrollbar parts */
  241.  
  242.       else if(whichpart==20)doscroll(whichpart,-1);  /* up button */
  243.       else if(whichpart==21)doscroll(whichpart,1);   /* down button */
  244.       else if(whichpart==22)doscroll(whichpart,-pagelines);  /* up page */
  245.       else if(whichpart==23)doscroll(whichpart,pagelines);  /* down page */
  246.       else if(whichpart==129)   /* in the thumb */
  247.          {      
  248.                  /* this next automatically tracks the mouse in */
  249.                  /* the thumb, and sets the ctlvalue for you */
  250.  
  251.          if(TRAP:W(TRACKCONTROL,scrollhnd:L,where:L,0:L)==129)  
  252.            scroll();
  253.          }
  254.       } 
  255.    return 0;
  256.    
  257. }
  258.  
  259. doscroll(whichpart,linestoscroll)
  260.    int    whichpart,linestoscroll;
  261.  
  262. {
  263.    int    wheremouse;
  264.  
  265.    while(TRAP:B(STILLDOWN))   /* If you haven't let go of the mouse yet */
  266.      {
  267.      TRAP(GETMOUSE,&wheremouse);  /* Where is it now? */
  268.      if(TRAP:W(TESTCONTROL,scrollhnd:L,wheremouse)==whichpart) /* there yet?*/
  269.        {                           
  270.        TRAP(HILITECONTROL,scrollhnd:L,whichpart:W);  /* hilite the part */
  271.        TRAP(SETCTLVALUE,scrollhnd:L,curtop+linestoscroll:W);
  272.        scroll();
  273.        }
  274.      else TRAP(HILITECONTROL,scrollhnd:L,0:W); /* turn off hilite */
  275.      }
  276.    TRAP(HILITECONTROL,scrollhnd:L,0:W); /* make sure you turn off hilite */
  277. }
  278.  
  279. selecttext(where)
  280.    int    where;
  281. {
  282.    if(TRAP:B(PTINRECT,where,&viewrect))  /* Is it in view? */
  283.       {
  284.       TRAP(TECLICK,where:L,0:B,tehnd);  /* Extend is always false here */
  285.       }
  286. }
  287.  
  288. /* This routine is boring, except that it shows how to use C */
  289. /* to find the record a handle ultimately points to.  Note here */
  290. /* we are getting the address of the te record in terec.  At the */
  291. /* address  + an offset of 94bytes is the number of lines in the */
  292. /* te record */
  293.  
  294. setscrollmax()
  295.  
  296. {
  297.    int   *temp;
  298.    char  *terec;
  299.  
  300.    if(tehnd!=0)
  301.      {
  302.      temp=tehnd;
  303.      terec=*temp;          /* terec+94 is number of lines of text */
  304.      TRAP(SETCTLMAX,scrollhnd:L,getword(terec+94):W); 
  305.      }
  306. }
  307.  
  308. scroll()
  309.  
  310. {
  311.     int     oldtop,numbtoscroll;
  312.  
  313.     oldtop=curtop;
  314.     curtop=TRAP:W(GETCTLVALUE,scrollhnd:L);
  315.     numbtoscroll= (oldtop-curtop)*11;  /* 11 is height of monaco 9 line */
  316.        /* scrolling 0 has been known to have strange effects, so we don't */
  317.     if(numbtoscroll!=0)TRAP(TESCROLL,0:W,numbtoscroll:W,tehnd:L);
  318. }
  319.  
  320. domenu(menuinfo)
  321.  
  322.    int  menuinfo;
  323. {
  324.    int    menu,menuitem;
  325.    int    in,volref;
  326.    char   filename[64],pfilename[64];
  327.  
  328.    menu=getword(&menuinfo);
  329.    menuitem=getword(&menuinfo+2);
  330.    if(menu==33)  /* file menu */
  331.      {
  332.      if (menuitem==1)
  333.        {   /* new window */
  334.        if(windptr==0)openwindow("untitled");
  335.        }
  336.      else if(menuitem==2)
  337.        {   /* open file and window */
  338.        if(windptr==0)
  339.          {
  340.          volref=getfile(filename);  /* returns 0 if cancelled */
  341.          if(volref)
  342.             {
  343.             openwindow(filename);
  344.             readfile(filename,volref);
  345.             }
  346.          }
  347.        }
  348.      else if(menuitem==3)
  349.        {
  350.        if(windptr!=0)
  351.          {
  352.          TRAP(GETWTITLE,windptr:L,&pfilename);
  353.          ptocstr(pfilename,filename);  /* this seems dumb */
  354.          volref=putfile(filename,"Save the file as...",filename);
  355.          if(volref)
  356.            {
  357.            writefile(filename,volref);
  358.            }
  359.          closewindow();  /* Close the window even if cancel save. */
  360.                          /* We really should go back to the window */
  361.                          /* but this is kept simple. */
  362.          }
  363.        }
  364.      else if(menuitem==8) return 1;       /* quitting time */
  365.      }
  366.    else if(menu==34) /* edit menu */
  367.      {
  368. /* An editorial comment: The Mac really makes cutting and pasting a snap */
  369. /* This next stuff is ridculously easy */
  370.  
  371.      if(menuitem==3)TRAP(TECUT,tehnd:L);
  372.      else if(menuitem==4)TRAP(TECOPY,tehnd:L);
  373.      else if(menuitem==5)TRAP(TEPASTE,tehnd:L);
  374.      else if(menuitem==6)TRAP(TEDELETE,tehnd:L);  /* clear */
  375.      else if(menuitem==7)TRAP(TESETSELECT,0:L,0XFFFF:L,tehnd:L); /* sel all*/
  376.      setscrollmax();
  377.      }
  378.    TRAP(HILITEMENU,0:W);  /* unlite all menus items */
  379.    return 0;
  380. }
  381.  
  382. /* Read a file into the te record.  It reads the entire file all */
  383. /* at once, which makes it rather fast. Everything here can be used */
  384. /* to do the regular kind of stuff... open a file, read a line into a */
  385. /* a buffer (rather than into the te record directly), read until you */
  386. /* reach an end of file, eventually close the file.  It is just a matter */
  387. /* of creating space for a buffer and then using these same things to */
  388. /* read into it a set amount repeatedly. I did it this way just to */
  389. /* show how to do it fast and neat */
  390.  
  391. /* Readfile and writefile use an assembler routine, PBIO, that requires */
  392. /* an address for the parameter block and a trap number. */
  393. /* In effect PBIO gives you access to all the PB routines */
  394. /* from the toolbox */
  395.  
  396. /* These routines really demonstrate how to play with non-simple */
  397. /* structures using C and the getword/putword routines.  It is a bit */
  398. /* of a pain to get just right.  If you have any problems, it is */
  399. /* useful to look at the assembler listing that the compiler */
  400. /* makes.  You do this by selecting C Compile with Listing... instead of */
  401. /* C Compile...   Another idea is to write in C or assembler some */
  402. /* simple conversion and assignment routines.  (that's what I'm going to do) */
  403.  
  404. /* One thing to be careful of is that pointers know what kind of thing */
  405. /* they point to.  In this case laddress+20 returns an address 80 bytes */
  406. /* offset from the value in laddress, while terec+20 returns an address */
  407. /* offset 20 bytes. */
  408.  
  409. readfile(filename,volref)
  410.    char    filename[];
  411.    int     volref;
  412.  
  413. {
  414.    char    pfilename[64];
  415.    char    *terec;
  416.    int     *laddress,*laddr2,retcode,i,filelen;
  417.  
  418. /* open the file */
  419.    
  420.  
  421.    for(i=0;i<100;i++)pblock[i]=0;  /* initialize pblock */
  422.    ctopstr(filename,pfilename);
  423.    laddress=&pblock[18];
  424.    *laddress=pfilename;            /* insert filename in pblock */
  425.    putword(&pblock[22],volref);    /* insert volrefnumber */
  426.    pblock[26]=0;                   /* set permission to 0 */
  427.    pblock[27]=1;                   /* set read permission */
  428.    laddress=&pblock[28];
  429.    *laddress=0;                    /* set buffer to nil to use volume buffer */
  430.    retcode=pbio(0XA000,&pblock);   /* open for read */
  431.  
  432.    if(retcode!=0) return retcode;   /* if error don't go on */
  433.  
  434. /* get filesize */
  435.  
  436.    retcode=pbio(0XA011,&pblock);   /* get eof */
  437.    laddress=&pblock[28];           /* size stored at offset 28 */
  438.    filelen=*laddress;
  439.  
  440.    if(retcode!=0) return retcode;   /* if error don't go on */
  441.  
  442. /* set text handlesize */
  443.  
  444.    laddress=tehnd;
  445.    terec=*laddress;
  446.    laddress=terec+62;  /* where the text handle is found */
  447.    retcode=sethandlesize(*laddress,filelen);   /* resize the text in terec */
  448.    
  449.    if(retcode!=0) return retcode;   /* if error don't go on */
  450.    
  451. /* read the entire file */
  452.    
  453.    laddress=tehnd;
  454.    terec=*laddress;
  455.    laddress=terec+62;  /* get the text handle */
  456.  
  457.    laddr2=*laddress;   /* get address of start of text */
  458.    laddr2=*laddr2;      /* I love handles, don't you? */
  459.    laddress=&pblock[32];
  460.    *laddress=laddr2;  /* put start of text address into pblock */
  461.    laddress=&pblock[36];
  462.    *laddress=filelen;
  463.    putword(&pblock[44],0);  /* no newline character */
  464.    laddress=&pblock[46];
  465.    *laddress=0;   /* set offset to 0 */
  466.    retcode=pbio(0XA002,&pblock);
  467.  
  468. /* close the file */
  469.  
  470.    retcode=pbio(0XA001,&pblock);   /* close it */
  471.  
  472.    recaltext(filelen);
  473.  
  474.  
  475. }
  476.  
  477. recaltext(filelen)
  478.  
  479.    int  filelen;
  480.  
  481. {
  482.    int  *laddress;
  483.    char *terec;
  484.  
  485.    laddress=tehnd;
  486.    terec=*laddress;
  487.    putword(terec+60,filelen);
  488.    TRAP(TECALTEXT,tehnd:L);
  489.    TRAP(TESETSELECT,0:L,0:L,tehnd:L);  /* set select to start */
  490.    setscrollmax();
  491. }
  492.  
  493. /* write the entire terecord out to a disk file */
  494.  
  495. writefile(filename,volref)
  496.  
  497.    char   filename[];
  498.    int    volref;
  499.  
  500. {
  501.    char    pfilename[64];
  502.    char    *terec;
  503.    int     *laddress,*laddr2,retcode,i,filelen;
  504.  
  505. /* open the file */
  506.    
  507.  
  508.    ctopstr(filename,pfilename);
  509.    laddress=&pblock[18];
  510.    *laddress=pfilename;            /* insert filename in pblock */
  511.    putword(&pblock[22],volref);    /* insert volrefnumber */
  512.    pblock[26]=0;                   /* set permission to 0 */
  513.    pblock[27]=2;                   /* set write permission */
  514.    laddress=&pblock[28];
  515.    *laddress=0;                    /* set buffer to nil to use volume buffer */
  516.    retcode=pbio(0XA000,&pblock);   /* open for write */
  517.  
  518. /* if file doesn't exist retcode=-43, so create it */
  519.    if(retcode==-43)retcode=createfile(filename,volref);
  520.  
  521.    if(retcode!=0) return retcode;   /* if error don't go on */
  522.    
  523. /*write the entire file */
  524.    
  525.    laddress=tehnd;
  526.    terec=*laddress;
  527.    laddress=terec+62;  /* get the text handle */
  528.    laddr2=*laddress;   /* get address of start of text */
  529.    filelen=getword(terec+60); /* get cur text length from terec */
  530.   
  531.    laddr2=*laddr2;      /* I love handles, don't you? */
  532.    laddress=&pblock[32];
  533.    *laddress=laddr2;  /* put start of text address into pblock */
  534.    laddress=&pblock[36];
  535.    *laddress=filelen;
  536.    putword(&pblock[44],1);  /* set pos mode for start of file */
  537.    laddress=&pblock[46];
  538.    *laddress=0;   /* set offset to 0 */
  539.    retcode=pbio(0XA003,&pblock);
  540.  
  541. /* set the file eof */
  542.  
  543.    laddress=&pblock[28];
  544.    laddr2=&pblock[40];
  545.    *laddress=*laddr2;  /* store the io count from write */
  546.    retcode=pbio(0XA012,&pblock);
  547.  
  548. /* close the file */
  549.  
  550.    retcode=pbio(0XA001,&pblock);   /* close it */
  551.  
  552. /* flush the volume */
  553.  
  554.    laddress=&pblock[18];
  555.    *laddress=0;                    /* set name to 0, volref is enough */
  556.    retcode=pbio(0XA013,&pblock);  /* flush away */
  557.  
  558. }
  559.  
  560.  
  561. createfile(filename,volref)
  562.  
  563.    char   filename[];
  564.    int    volref;
  565.  
  566. {
  567.    char    pfilename[64];
  568.    char    *terec;
  569.    int     *laddress,*laddr2,retcode,i,filelen;
  570.  
  571. /* open the file */
  572.    
  573.  
  574.    ctopstr(filename,pfilename);
  575.    laddress=&pblock[18];
  576.    *laddress=pfilename;            /* insert filename in pblock */
  577.    putword(&pblock[22],volref);    /* insert volrefnumber */
  578.    pblock[26]=0;                   /* set version to 0 */
  579.    retcode=pbio(0XA008,&pblock);   /* create it */
  580.  
  581.    if(retcode!=0) return retcode;
  582.  
  583. /* get the fileinfo */
  584.  
  585.    laddress=&pblock[18];
  586.    *laddress=pfilename;            /* insert filename in pblock */
  587.    putword(&pblock[22],volref);    /* insert volrefnumber */
  588.    pblock[26]=0;                   /* set version to 0 */
  589.    putword(&pblock[28],0);         /* set dir index to 0 */
  590.    retcode=pbio(0XA00C,&pblock);   /* get file info */
  591.  
  592. /* set the fileinfo */
  593. /* use the fileinfo we just got, and set type to text */
  594.  
  595.    pblock[32]='T';
  596.    pblock[33]='E';
  597.    pblock[34]='X';
  598.    pblock[35]='T';
  599.  
  600. /* you could set the creator to something here */
  601.  
  602.    retcode=pbio(0XA00D,&pblock);   /* set file info */
  603.  
  604. /* now try opening it again */
  605.   
  606.    laddress=&pblock[18];
  607.    *laddress=pfilename;            /* insert filename in pblock */
  608.    putword(&pblock[22],volref);    /* insert volrefnumber */
  609.    pblock[26]=0;                   /* set permission to 0 */
  610.    pblock[27]=2;                   /* set write permission */
  611.    laddress=&pblock[28];
  612.    *laddress=0;                    /* set buffer to nil to use volume buffer */
  613.    retcode=pbio(0XA000,&pblock);   /* open for write */
  614.  
  615.    return retcode;
  616. }
  617.  
  618.  
  619. /* output a decimal number  */
  620. outdec(n)
  621. int n;
  622. {
  623.        if(n<0)
  624.                putachar('-');
  625.        else    n = -n;
  626.        outint(n);
  627. /* end outdec */}
  628.  
  629. outint(n)      
  630. int n;
  631. {      int q;
  632.  
  633.        q = n/10;
  634.        if(q) outint(q);
  635.        putachar('0'-(n-q*10));
  636. /* end outint */}
  637.  
  638. wait()
  639. {
  640.    int event;
  641.  
  642.    while(1)
  643.      {
  644.      if(TRAP:B(GETNEXTEVENT,0XFFFF:W,&seventrec)) /* trap any event */
  645.        {
  646.        event=getword(&seventrec);  
  647.        if(event==1)break; /* mouse */
  648.        if(event==3)break; /* keydown */
  649.        }
  650.      }
  651. }